var fs = require("fs");
var d3 = require('d3');
var url = require("url");
var path = require('path');
var ep = require('easy-proj');
var png = require('pngjs').PNG;
var mkdirp = require('mkdirp');
var cache = require('memory-cache');

var decoder = require("./decoder");
var product = require("./product");
var configer = require("./configer");

function start(response, request) {

    var pathname = url.parse(request.url).pathname;
    var pars = pathname.split("/");

    if (pars.length != 6) {
        errorpage(response, pathname);
        return;
    }

    //图像类型
    var type = pars[1];
    //数据时间201609091030 年月日时间分
    //        201706070000
    var datadt = pars[2];
    var z = pars[3];
    var x = pars[4];
    var y = pars[5];
    if (!product.product[type]) {
        //var fs = require("fs");
        fs.readFile("/dataxiu/websites/creator/nodata.png", function (error, data) {
            if (error) throw error;
            response.write(data);
            response.end();
        });
        return;
    }
    var pro = product.product[type];
    //元数据文件位置和名称
    var fullname = "";
    var filename = "";
    //构建文件请求路径
    //如果是current，表示当前   
    if (datadt === "current") {
        filename = pro.file;
        fullname = configer.sourcepath + "webdata/data/" + pro.source + "/current/" + filename;
    } else {
        filename = pro.tmplet.replace("{HHmm}", datadt.substr(8, 4));
        //如果是时间形式的，需要重新处理 201708091130 
        fullname = configer.sourcepath + "webdata/data/" + pro.source + "/" + datadt.substr(0, 4) + "/" + datadt.substr(4, 2) + "/" + datadt.substr(6, 2) + "/" + filename;
    }
    console.info(fullname);
    //从缓存获取当前文件
    //fullname = "D:/a2map/webdata/data/geos/current/current-cosc-geos.epak";

    var packdata = cache.get(fullname);

    if (!packdata) {
        fs.readFile(fullname, function (error, data) {

            if (error) throw error;

            var buffer = new Uint8Array(data).buffer;
            packdata = decoder.decodeEpak(buffer);
            //Float32Array 
            //数据变换成从-180 到 180的经纬度区间
            var imgwidth = packdata.header.variables.lon.sequence.size;
            var imgheight = packdata.header.variables.lat.sequence.size;

            var wrapdata = new Float32Array(packdata.blocks[0].length);

            for (var irow = 0; irow < imgheight; irow++) {
                var sub1 = packdata.blocks[0].subarray(irow * imgwidth + imgwidth / 2, (irow + 1) * imgwidth);
                wrapdata.set(sub1, irow * imgwidth);

                var sub0 = packdata.blocks[0].subarray(irow * imgwidth, irow * imgwidth + imgwidth / 2);
                wrapdata.set(sub0, irow * imgwidth + imgwidth / 2);
            }
            packdata.blocks[0] = wrapdata;

            cache.put(fullname, packdata);
            createimg(response, request, pro, packdata, x, y, z);
        });
    } else {
        createimg(response, request, pro, packdata, x, y, z);
    }
}
/*
请求格式发生错误，默认发生一个空白图片
*/
function errorpage(response, pathname) {
    console.log("Request handler 'error' was called.");
    response.writeHead(200, {
        "Content-Type": "image/png",
        "Access-Control-Allow-Origin": "*"
    });
    var fs = require("fs");
    fs.readFile("/dataxiu/websites/creator/nodata.png", function (error, data) {
        if (error) throw error;
        response.write(data);
        response.end();
    });
}

/*
双线性插值计算vp的值
q12     q22

    p

q11     q21
*/
function linear(q12, q22, q11, q21, p) {
    var vr1, vr2, vp;
    if (q22.x === q12.x || q21.x === q11.x) {
        vp = (p.y - q11.y) / (q12.y - q11.y) * (q12.v - q11.v) + q11.v;
    } else if (q12.y === q11.y || q22.y === q11.y) {
        vp = (p.x - q12.x) / (q22.x - q12.x) * (q22.v - q12.v) + q12.v;
    } else {
        vr2 = (p.x - q12.x) / (q22.x - q12.x) * (q22.v - q12.v) + q12.v;
        vr1 = (p.x - q11.x) / (q21.x - q11.x) * (q21.v - q11.v) + q11.v;
        vp = (p.y - q11.y) / (q12.y - q11.y) * (vr2 - vr1) + vr1;
    }

    return vp;
}

function createimg(response, request, pro, pakdata, gisx, gisy, gisz) {

    //算法，这个比较麻烦，好处是可以做成并行的模式，就是每图块都可以用一个应用处理，
    //1：根据放大级别和图片位置，
    //2: 轮询图片上每个像素，根据像素计算出经纬度坐标
    //3：根据坐标，获取包围当前坐标的4个点位置，进行双线性插值，计算出当前点的值
    //4：根据但前点的值，获取d3颜色插值结果，完成图片

    var offsetx = 256 * gisx;
    var offsety = 256 * gisy;

    var width = 256,
        height = 256;


    var newfile = new png({
        deflateLevel: 1,
        filterType: 4,
        colorType: 6,
        width: width,
        height: height,
        bgColor: 0xffffff
    });
    //把数据重新打包成二维的标准格式,从-180 180 -90 90的排布

    var wfbl = Math.abs(pakdata.header.variables.lon.sequence.delta);
    var hfbl = Math.abs(pakdata.header.variables.lon.sequence.delta);
    var imgwidth = pakdata.header.variables.lon.sequence.size;
    var imgheight = pakdata.header.variables.lat.sequence.size;

    var color = pro.color;

    var rawdata = pakdata.blocks[0];

    for (var y = 0; y < height; y++) {
        for (var x = 0; x < width; x++) {
            var idx = (width * y + x) << 2;

            //默认数据说明
            //经度个格点间隔是.3125
            //纬度格点数据是.25

            //计算出当前点的经纬度[x,y]     

            var pxy = ep.pixel2lnglat(offsetx + parseInt(x), offsety + parseInt(y), gisz);

            //获取包围当前点的最小的四个点,求出来的是数据偏移
            var tmpxmin = Math.floor((pxy[0]) / wfbl);
            var tmpymin = Math.floor((pxy[1]) / hfbl);


            var tmpxmax = tmpxmin + 1; //  
            var tmpymax = tmpymin + 1; //;  

            var tmpxmax1 = Math.ceil((pxy[0]) / wfbl);
            if (tmpxmax1 === tmpxmin) {
                tmpxmax = tmpxmin;
            }
            var tmpymax1 = Math.ceil((pxy[1]) / hfbl);
            if (tmpymax1 === tmpymin) {
                tmpymax = tmpymin;
            }

            //

            var tmpxmin1 = (tmpxmin) + 180 / wfbl; //  
            var tmpymin1 = (tmpymin) + 90 / hfbl; // 
            var tmpxmax1 = (tmpxmax) + 180 / wfbl;
            var tmpymax1 = (tmpymax) + 90 / hfbl;

            //数据偏移索引值
            var index1 = imgwidth * (imgheight - tmpymax1) + tmpxmin1;
            var index2 = imgwidth * (imgheight - tmpymax1) + tmpxmax1;
            var index3 = imgwidth * (imgheight - tmpymin1) + tmpxmin1;
            var index4 = imgwidth * (imgheight - tmpymin1) + tmpxmax1;

            var q12, q22, q11, q21, p;
            /*
            双线性插值计算vp的值
            q12     q22

                p

            q11     q21
            */

            //从数据文件中读取对应的数值
            q12 = {
                x: (parseFloat(tmpxmin)) * wfbl,
                y: parseFloat(tmpymax) * hfbl,
                v: rawdata[index1] // datas[tmpymin+1][tmpxmin]//
            };

            q22 = {
                x: parseFloat(tmpxmax) * wfbl,
                y: parseFloat(tmpymax) * hfbl,
                v: rawdata[index2] //datas[tmpymin+1][tmpxmin+1]//
            };

            q11 = {
                x: parseFloat(tmpxmin) * wfbl,
                y: parseFloat(tmpymin) * hfbl,
                v: rawdata[index3] //datas[tmpymin][tmpxmin]//
            };

            q21 = {
                x: parseFloat(tmpxmax) * wfbl,
                y: parseFloat(tmpymin) * hfbl,
                v: rawdata[index4] //datas[tmpymin][tmpxmin+1]//
            };
            p = {
                x: pxy[0],
                y: pxy[1]
            };

            var v = linear(q12, q22, q11, q21, p);

            //传入数据
            /*console.info("开始打印");
			console.info("像素：x"+parseInt(x) +"   y"+parseInt(y)+"   z"+gisz);
			console.info("位置："+pxy);
			console.info("范围：tmpxmin"+tmpxmin +"   tmpymin" +tmpymin + "   tmpxmax"+tmpxmax +"   tmpymax" +tmpymax);
			console.info("索引"+index);		
			
			console.info("输入值");
			console.info(q12);
			console.info(q22);
			console.info(q11);
			console.info(q21);
			console.info(p);
			
			console.info("返回值"+v);
           */
            //获取到颜色值了
            //console.info(v);
            c = d3.rgb(color(v));

            newfile.data[idx] = c.r;
            newfile.data[idx + 1] = c.g;
            newfile.data[idx + 2] = c.b;
            newfile.data[idx + 3] = 0xbb;

        }
    }

    response.writeHead(200, {
        "Content-Type": "image/png",
        "Access-Control-Allow-Origin": "*"
    });
    var urlname = url.parse(request.url).pathname; //路径名称
    //console.info(path.dirname(pathname)); 目录名称
    //console.info(path.basename(pathname)); 文件名称
    var filepath = configer.imagepath + path.dirname(urlname);
    var fullname = filepath + "/" + path.basename(urlname) + ".png";
    fs.exists(filepath, function (exists) {
        if (exists) {
            newfile.pack().pipe(fs.createWriteStream(fullname)).on('finish', function () {
                fs.createReadStream(fullname).pipe(response);
            });
        } else {
            mkdirp(filepath, function (err) {
                newfile.pack().pipe(fs.createWriteStream(fullname)).on('finish', function () {
                    fs.createReadStream(fullname).pipe(response);
                });
            });
        }
    });

    //newfile.pack().pipe(response);

}
exports.start = start;